/**
 **********************************************************************************************************************
 * @file    cot_param.c
 * @brief   该文件提供参数管理框架功能
 * @note    功能详细说明：
 *           + 参数修改和重置管理
 *           + 参数序列化和反序列化
 * 数据序列化格式：
 * | 支持数目(1) | 数据1的长度和ID(0.5+0.5) | 数据1(n) | 数据2的长度和ID(1) | 数据2(n) | 数据3的长度和ID(1) | 数据3(n) |
 * | 支持数目(1) | 数据1的长度和ID(1.0+1.0) | 数据1(n) | 数据2的长度和ID(2) | 数据2(n) | 数据3的长度和ID(2) | 数据3(n) |
 * | 支持数目(1) | 数据1的长度和ID(1.5+1.5) | 数据1(n) | 数据2的长度和ID(3) | 数据2(n) | 数据3的长度和ID(3) | 数据3(n) |
 **********************************************************************************************************************
 */

/* Includes ----------------------------------------------------------------------------------------------------------*/
#include "cot_param.h"
#include <string.h>
#include <stdio.h>

/**
 * @brief      参数值联合体
 *
 * @note       用于存储不同类型的参数值，支持整数、浮点数和字符串类型
 */
typedef union
{
    uint64_t u64val; /* 无符号64位整数值 */
    int64_t s64val;  /* 有符号64位整数值 */
    double fVal;     /* 双精度浮点数值 */
#if COT_PARAM_USE_STRING_TYPE
    char str[COT_PARAM_STRING_MAX_LENGTH]; /* 字符串值，最大长度由COT_PARAM_STRING_MAX_LENGTH定义 */
#endif
} Value_u;

static cotParamCheckRet_e ValidateRangeByVoid(const cotParamInfo_t *pParam, const void *pval);

/**
 * @brief      序列化无符号整数
 *
 * @param[in,out] ptr   序列化数据存储指针
 * @param[in]     value 待序列化的无符号整数值
 * @param[in]     len   序列化的字节长度
 *
 * @note       将无符号整数按小端序转换为字节流
 *
 * @retval     uint8_t* 返回序列化后的数据指针位置
 */
uint8_t *SerializeUint(uint8_t *ptr, uint64_t value, uint8_t len)
{
    /* 按字节序列化无符号整数 */
    for (int i = 0; i < len; i++)
    {
        *ptr++ = value >> (i * 8);
    }

    return ptr;
}

/**
 * @brief      序列化有符号整数
 *
 * @param[in,out] ptr   序列化数据存储指针
 * @param[in]     value 待序列化的有符号整数值
 * @param[in]     len   序列化的字节长度
 *
 * @note       将有符号整数按小端序转换为字节流
 *
 * @retval     uint8_t* 返回序列化后的数据指针位置
 */
static uint8_t *SerializeInt(uint8_t *ptr, int64_t value, uint8_t len)
{
    /* 按字节序列化有符号整数 */
    for (int i = 0; i < len; i++)
    {
        *ptr++ = value >> (i * 8);
    }

    return ptr;
}

/**
 * @brief      序列化单精度浮点数
 *
 * @param[in,out] ptr   序列化数据存储指针
 * @param[in]     value 待序列化的浮点数值
 *
 * @note       将单精度浮点数按IEEE-754格式转换为字节流
 *
 * @retval     uint8_t* 返回序列化后的数据指针位置
 */
static uint8_t *SerializeFloat(uint8_t *ptr, float value)
{
    /* 将浮点数转换为无符号整数进行序列化 */
    uint32_t ivalue = *((uint32_t *)&value);

    /* 按字节序列化浮点数 */
    for (int i = 0; i < sizeof(ivalue); i++)
    {
        *ptr++ = ivalue >> (i * 8);
    }

    return ptr;
}

/**
 * @brief      序列化双精度浮点数
 *
 * @param[in,out] ptr   序列化数据存储指针
 * @param[in]     value 待序列化的双精度浮点数值
 *
 * @note       将双精度浮点数按IEEE-754格式转换为字节流
 *
 * @retval     uint8_t* 返回序列化后的数据指针位置
 */
static uint8_t *SerializeDouble(uint8_t *ptr, double value)
{
    /* 将双精度浮点数转换为无符号整数进行序列化 */
    uint64_t ivalue = *((uint64_t *)&value);

    /* 按字节序列化双精度浮点数 */
    for (int i = 0; i < sizeof(ivalue); i++)
    {
        *ptr++ = ivalue >> (i * 8);
    }

    return ptr;
}

/**
 * @brief      反序列化无符号整数
 *
 * @param[in]  ptr    待反序列化的数据指针
 * @param[out] value  反序列化后的无符号整数值
 * @param[in]  len    反序列化的字节长度
 *
 * @note       将字节流按小端序转换为无符号整数
 *
 * @retval     uint8_t* 返回反序列化后的数据指针位置
 */
static uint8_t *UnSerializeUint(const uint8_t *ptr, uint64_t *value, uint8_t len)
{
    /* 初始化输出值 */
    *value = 0;

    /* 按字节反序列化无符号整数 */
    for (int i = 0; i < len; i++)
    {
        *value |= (uint64_t)(*ptr++) << (i * 8);
    }

    return (uint8_t *)ptr;
}

/**
 * @brief      反序列化有符号整数
 *
 * @param[in]  ptr    待反序列化的数据指针
 * @param[out] value  反序列化后的有符号整数值
 * @param[in]  len    反序列化的字节长度
 *
 * @note       将字节流按小端序转换为有符号整数
 *
 * @retval     uint8_t* 返回反序列化后的数据指针位置
 */
static uint8_t *UnSerializeInt(const uint8_t *ptr, int64_t *value, uint8_t len)
{
    /* 初始化输出值 */
    *value = 0;

    /* 按字节反序列化有符号整数 */
    for (int i = 0; i < len; i++)
    {
        *value |= (int64_t)(*ptr++) << (i * 8);
    }

    return (uint8_t *)ptr;
}

/**
 * @brief      反序列化单精度浮点数
 *
 * @param[in]  ptr    待反序列化的数据指针
 * @param[out] value  反序列化后的浮点数值
 *
 * @note       将字节流按IEEE-754格式转换为单精度浮点数
 *
 * @retval     uint8_t* 返回反序列化后的数据指针位置
 */
static uint8_t *UnSerializeFloat(const uint8_t *ptr, float *value)
{
    /* 初始化临时变量 */
    uint32_t ivalue = 0;

    /* 按字节反序列化为无符号整数 */
    for (int i = 0; i < sizeof(ivalue); i++)
    {
        ivalue |= (uint32_t)(*ptr++) << (i * 8);
    }

    /* 将无符号整数转换为浮点数 */
    *value = *((float *)&ivalue);

    return (uint8_t *)ptr;
}

/**
 * @brief      反序列化双精度浮点数
 *
 * @param[in]  ptr    待反序列化的数据指针
 * @param[out] value  反序列化后的双精度浮点数值
 *
 * @note       将字节流按IEEE-754格式转换为双精度浮点数
 *
 * @retval     uint8_t* 返回反序列化后的数据指针位置
 */
static uint8_t *UnSerializeDouble(const uint8_t *ptr, double *value)
{
    /* 初始化临时变量 */
    uint64_t ivalue = 0;

    /* 按字节反序列化为无符号整数 */
    for (int i = 0; i < sizeof(ivalue); i++)
    {
        ivalue |= (uint64_t)(*ptr++) << (i * 8);
    }

    /* 将无符号整数转换为双精度浮点数 */
    *value = *((double *)&ivalue);

    return (uint8_t *)ptr;
}

/**
 * @brief      重置参数为默认值
 *
 * @param[in]  pParam    参数信息结构体指针
 *
 * @note       根据参数类型将参数值重置为默认值，支持数值类型和字符串类型
 *
 * @retval     true      重置成功
 * @retval     false     重置失败或无需重置
 */
static bool ResetParamValue(const cotParamInfo_t *pParam)
{
    /* 检查参数是否可重置 */
    if (pParam != NULL && (pParam->attr & COT_PARAM_ATTR_RESET))
    {
#if COT_PARAM_USE_STRING_TYPE
        /* 区分字符串类型和其他类型的重置方式 */
        if (pParam->type != COT_PARAM_STRING)
        {
            /* 数值类型使用内存拷贝 */
            memcpy(pParam->unCurValuePtr.pVoid, pParam->unDefValuePtr.pVoid, pParam->length);
        }
        else
        {
            /* 字符串类型使用字符串拷贝 */
            strcpy(pParam->unCurValuePtr.pString, pParam->unDefValuePtr.pString);
        }
#else
        /* 不支持字符串类型时直接使用内存拷贝 */
        memcpy(pParam->unCurValuePtr.pVoid, pParam->unDefValuePtr.pVoid, pParam->length);
#endif
        return true;
    }

    return false;
}

/**
 * @brief      重置参数为最小值
 *
 * @param[in]  pParam    参数信息结构体指针
 *
 * @note       将参数值重置为允许的最小值，仅支持数值类型参数
 *
 * @retval     true      重置成功
 * @retval     false     重置失败或无需重置
 */
static bool ResetParamMinValue(const cotParamInfo_t *pParam)
{
    /* 检查参数是否支持范围限制 */
    if (pParam != NULL && (pParam->attr & COT_PARAM_ATTR_RANGE))
    {
#if COT_PARAM_USE_STRING_TYPE
        /* 字符串类型不支持最小值重置 */
        if (pParam->type != COT_PARAM_STRING)
#endif
        {
            /* 将参数值设置为最小值 */
            memcpy(pParam->unCurValuePtr.pVoid, pParam->unMinValuePtr.pVoid, pParam->length);
        }

        return true;
    }

    return false;
}

/**
 * @brief      重置参数为最大值
 *
 * @param[in]  pParam    参数信息结构体指针
 *
 * @note       将参数值重置为允许的最大值，支持数值类型和字符串类型
 *
 * @retval     true      重置成功
 * @retval     false     重置失败或无需重置
 */
static bool ResetParamMaxValue(const cotParamInfo_t *pParam)
{
    /* 检查参数是否支持范围限制 */
    if (pParam != NULL && (pParam->attr & COT_PARAM_ATTR_RANGE))
    {
#if COT_PARAM_USE_STRING_TYPE
        /* 字符串类型特殊处理，截断到最大长度 */
        if (pParam->type == COT_PARAM_STRING)
        {
            /* 在最大长度位置添加字符串结束符 */
            pParam->unCurValuePtr.pString[*pParam->unMaxValuePtr.pStringLength] = 0;
        }
        else
#endif
        {
            /* 数值类型直接设置为最大值 */
            memcpy(pParam->unCurValuePtr.pVoid, pParam->unMaxValuePtr.pVoid, pParam->length);
        }

        return true;
    }

    return false;
}

/**
 * @brief      参数表初始化
 *
 * @param[in]  pManager    参数表管理句柄
 * @param[in]  pParamTable 参数表
 * @param[in]  count       参数表元素数目, 可以通过宏 COT_PARAM_TABLE_SIZE 获取
 *
 * @note       初始化参数管理器，设置参数表和参数数量
 *
 * @retval     0           成功
 * @retval     -1          失败
 */
int cotParam_Init(cotParamManager_t *pManager, cotParamInfo_t *pParamTable, uint16_t count)
{
    /* 参数有效性检查 */
    if (pManager == NULL || pParamTable == NULL)
    {
        return -1;
    }

    /* 遍历参数表进行初始化检查和属性设置 */
    for (uint16_t i = 0; i < count; i++)
    {
        /* 检查最大/最小值指针，如果为空则清除范围检查属性 */
        if (pParamTable[i].unMaxValuePtr.pVoid == NULL || pParamTable[i].unMinValuePtr.pVoid == NULL)
        {
            pParamTable[i].attr &= ~COT_PARAM_ATTR_RANGE;
        }

        /* 如果没有读权限，则清除写权限 */
        if (!(pParamTable[i].attr & COT_PARAM_ATTR_READ))
        {
            pParamTable[i].attr &= ~COT_PARAM_ATTR_WRITE;
        }

        /* 如果默认值指针为空，则清除重置属性 */
        if (pParamTable[i].unDefValuePtr.pVoid == NULL)
        {
            pParamTable[i].attr &= ~COT_PARAM_ATTR_RESET;
        }

        /* 当前值指针必须有效，否则初始化失败 */
        if (pParamTable[i].unCurValuePtr.pVoid == NULL)
        {
            return -1;
        }
    }

    /* 初始化参数管理器结构体 */
    pManager->pParamTable = pParamTable;
    pManager->count = count;
    return 0;
}

/**
 * @brief      重置所有参数，恢复为缺省值
 *
 * @param[in]  pManager    参数表管理句柄
 *
 * @note       无可重置权限的参数不能恢复为缺省值
 *
 * @retval     0           成功
 * @retval     -1          失败
 */
int cotParam_ResetDefault(const cotParamManager_t *pManager)
{
    /* 参数有效性检查 */
    if (pManager == NULL)
    {
        return -1;
    }

    /* 遍历参数表，重置每个参数为默认值 */
    for (uint16_t i = 0; i < pManager->count; ++i)
    {
        /* 调用重置函数，只有具有重置属性的参数会被重置 */
        ResetParamValue(&pManager->pParamTable[i]);
    }

    return 0;
}

/**
 * @brief      检查所有参数当前值的范围并对超出范围时进行处理
 *
 * @param[in]  pManager        参数表管理句柄
 * @param[in]  pfnCheckError   参数超出范围时的处理函数
 *
 * @note       如果参数有自定义校验方式，则只有满足范围校验成功的前提下才会执行自定义校验
 *
 * @retval     0           成功
 * @retval     -1          失败
 */
int cotParam_Check(const cotParamManager_t *pManager, cotParamError_f pfnCheckError)
{
    cotParamCheckRet_e eCheckResult;

    /* 参数有效性检查 */
    if (pManager == NULL)
    {
        return -1;
    }

    /* 遍历参数表进行参数检查 */
    for (int id = 0; id < pManager->count; id++)
    {
        /* 首先进行范围检查 */
        eCheckResult = ValidateRangeByVoid(&pManager->pParamTable[id], pManager->pParamTable[id].unCurValuePtr.pVoid);

        /* 如果范围检查失败，调用错误处理回调 */
        if (COT_PARAM_CHECK_OK != eCheckResult)
        {
            if (pfnCheckError != NULL)
            {
                pfnCheckError(&pManager->pParamTable[id], eCheckResult);
            }
        }
        else
        {
#if COT_PARAM_USE_CUSTOM_CHECK
            /* 范围检查通过后，执行自定义检查 */
            if (pManager->pParamTable[id].pfnParamCheck != NULL)
            {
                if (pManager->pParamTable[id].pfnParamCheck(pManager->pParamTable[id].unCurValuePtr.pVoid) != 0)
                {
                    if (pfnCheckError != NULL)
                    {
                        pfnCheckError(&pManager->pParamTable[id], COT_PARAM_CHECK_OTHER_ERR);
                    }
                }
            }
#endif
        }
    }

    return 0;
}

/**
 * @brief      根据参数指针查找参数信息
 *
 * @param[in]  pManager      参数管理器句柄
 * @param[in]  curParamPtr   参数当前值的指针
 *
 * @note       遍历参数表，根据参数值的内存地址查找对应的参数信息
 *
 * @retval     cotParamInfo_t*  找到的参数信息结构体指针
 * @retval     NULL             未找到对应参数
 */
static cotParamInfo_t *FindParamByParamPtr(const cotParamManager_t *pManager, const void *curParamPtr)
{
    /* 遍历参数表查找匹配的参数指针 */
    for (uint16_t i = 0; i < pManager->count; ++i)
    {
        if (pManager->pParamTable[i].unCurValuePtr.pVoid == curParamPtr)
        {
            return &pManager->pParamTable[i];
        }
    }

    return NULL;
}

/**
 * @brief      参数列表迭代器
 *
 * @param[in]     pManager    参数管理器句柄
 * @param[in,out] psIdx       迭代索引指针，用于记录当前遍历位置
 *
 * @note       该函数实现了参数表的迭代访问功能：
 *             1. 首先进行参数有效性检查，确保管理器句柄、索引指针有效且索引值在合理范围内
 *             2. 从当前索引位置开始遍历参数表
 *             3. 对于每个参数，检查是否具有读取权限
 *             4. 如果具有读取权限，返回该参数信息并更新索引
 *             5. 如果不具有读取权限，继续遍历下一个参数
 *             6. 当遍历完所有参数后返回NULL
 *
 * @retval     cotParamInfo_t*  当前索引位置的参数信息
 * @retval     NULL             遍历结束
 */
cotParamInfo_t *cotParam_IterateList(const cotParamManager_t *pManager, size_t *psIdx)
{
    cotParamInfo_t *p = NULL;

    /* 参数有效性检查：确保管理器句柄、索引指针有效且索引值在合理范围内 */
    if (pManager == NULL || psIdx == NULL || *psIdx > pManager->count)
    {
        return NULL;
    }

    /* 从当前索引位置开始遍历参数表 */
    while (*psIdx < pManager->count)
    {
        /* 检查当前参数是否具有读取权限 */
        if (pManager->pParamTable[*psIdx].attr & COT_PARAM_ATTR_READ)
        {
            /* 找到可读参数，获取其地址并更新索引 */
            p = &pManager->pParamTable[*psIdx];
            (*psIdx)++;
            break;
        }

        /* 当前参数不可读，继续检查下一个 */
        (*psIdx)++;
    }

    /* 返回找到的参数信息或NULL（如果遍历结束） */
    return p;
}

/**
 * @brief      根据参数ID查找参数信息
 *
 * @param[in]  pManager    参数管理器句柄
 * @param[in]  id          参数ID
 *
 * @note       遍历参数表，根据参数ID查找对应的参数信息
 *
 * @retval     cotParamInfo_t*  找到的参数信息结构体指针
 * @retval     NULL             未找到对应参数
 */
static cotParamInfo_t *FindParamByID(const cotParamManager_t *pManager, uint16_t id)
{
    /* 遍历参数表查找匹配的参数ID */
    for (uint16_t i = 0; i < pManager->count; ++i)
    {
        if (pManager->pParamTable[i].id == id)
        {
            return &pManager->pParamTable[i];
        }
    }

    return NULL;
}

/**
 * @brief      根据参数ID查找参数信息
 *
 * @param[in]  pManager    参数管理器句柄
 * @param[in]  id          要查找的参数ID
 *
 * @note       该函数通过参数ID查找对应的参数信息：
 *             1. 首先检查参数管理器句柄的有效性
 *             2. 调用内部查找函数FindParamByID在参数表中搜索指定ID
 *             3. 如果找到参数，检查其是否具有读取权限
 *             4. 只有同时满足找到参数且具有读取权限时才返回参数信息
 *             5. 其他情况均返回NULL
 *
 * @retval     const cotParamInfo_t*  找到的参数信息指针（具有读取权限）
 * @retval     NULL                   未找到对应参数或无读取权限
 */
const cotParamInfo_t *cotParam_FindParamByID(const cotParamManager_t *pManager, uint16_t id)
{
    cotParamInfo_t *pInfo;

    /* 检查参数管理器句柄的有效性 */
    if (pManager != NULL)
    {
        /* 在参数表中查找指定ID的参数 */
        pInfo = FindParamByID(pManager, id);

        /* 检查找到的参数是否具有读取权限 */
        if (pInfo->attr & COT_PARAM_ATTR_READ)
        {
            /* 参数可读，返回参数信息 */
            return pInfo;
        }
    }

    /* 参数管理器无效或参数不可读，返回NULL */
    return NULL;
}

/**
 * @brief      根据参数指针查找参数信息
 *
 * @param[in]  pManager    参数管理器句柄
 * @param[in]  pCurParam   参数当前值的指针
 *
 * @note       该函数通过参数值的内存地址查找对应的参数信息：
 *             1. 首先检查参数管理器句柄和参数指针的有效性
 *             2. 调用内部查找函数FindParamByParamPtr在参数表中搜索指定指针
 *             3. 如果找到参数，检查其是否具有读取权限
 *             4. 只有同时满足找到参数且具有读取权限时才返回参数信息
 *             5. 其他情况均返回NULL
 *
 * @retval     const cotParamInfo_t*  找到的参数信息指针（具有读取权限）
 * @retval     NULL                   未找到对应参数或无读取权限
 */
const cotParamInfo_t *cotParam_FindParamByParamPtr(const cotParamManager_t *pManager, const void *pCurParam)
{
    cotParamInfo_t *pInfo;

    /* 检查参数管理器句柄和参数指针的有效性 */
    if (pManager != NULL || pCurParam != NULL)
    {
        /* 根据参数值的内存地址查找对应的参数信息 */
        pInfo = FindParamByParamPtr(pManager, pCurParam);

        /* 检查找到的参数是否具有读取权限 */
        if (pInfo->attr & COT_PARAM_ATTR_READ)
        {
            /* 参数可读，返回参数信息 */
            return pInfo;
        }
    }

    /* 参数管理器或参数指针无效，或参数不可读，返回NULL */
    return NULL;
}

/**
 * @brief      验证参数值是否在有效范围内
 *
 * @param[in]  pParam    参数信息结构体指针
 * @param[in]  pval      待验证的参数值
 *
 * @note       该函数实现参数值的范围验证：
 *             1. 首先检查参数是否启用了范围检查属性
 *             2. 根据参数类型选择相应的比较方式：
 *                - 整数类型(有符号/无符号)：直接比较数值大小
 *                - 浮点类型：按IEEE-754格式比较
 *                - 字符串类型：比较长度范围
 *             3. 将参数值与最小值和最大值比较
 *             4. 返回相应的验证结果
 *
 * @retval     COT_PARAM_CHECK_OK        验证通过
 * @retval     COT_PARAM_CHECK_OVER_MIN  小于最小值
 * @retval     COT_PARAM_CHECK_OVER_MAX  大于最大值
 */
static cotParamCheckRet_e ValidateRange(const cotParamInfo_t *pParam, const Value_u *pval)
{
    /* 首先检查参数是否启用了范围检查属性 */
    if (!(pParam->attr & COT_PARAM_ATTR_RANGE))
    {
        /* 如果未启用范围检查，直接返回验证通过 */
        return COT_PARAM_CHECK_OK;
    }

    /* 根据参数类型选择相应的比较方式进行范围验证 */
    switch (pParam->type)
    {
        /* 有符号整数类型的范围验证 */
        case COT_PARAM_INT8:
            /* 检查是否小于最小值 */
            if (pval->s64val < *pParam->unMinValuePtr.pInt8)
            {
                return COT_PARAM_CHECK_OVER_MIN;
            }
            /* 检查是否大于最大值 */
            else if (pval->s64val > *pParam->unMaxValuePtr.pInt8)
            {
                return COT_PARAM_CHECK_OVER_MAX;
            }
            break;

        case COT_PARAM_INT16:
            /* 检查16位有符号整数是否小于最小值 */
            if (pval->s64val < *pParam->unMinValuePtr.pInt16)
            {
                return COT_PARAM_CHECK_OVER_MIN;
            }
            /* 检查16位有符号整数是否大于最大值 */
            else if (pval->s64val > *pParam->unMaxValuePtr.pInt16)
            {
                return COT_PARAM_CHECK_OVER_MAX;
            }
            break;

        case COT_PARAM_INT32:
            /* 检查32位有符号整数是否小于最小值 */
            if (pval->s64val < *pParam->unMinValuePtr.pInt32)
            {
                return COT_PARAM_CHECK_OVER_MIN;
            }
            /* 检查32位有符号整数是否大于最大值 */
            else if (pval->s64val > *pParam->unMaxValuePtr.pInt32)
            {
                return COT_PARAM_CHECK_OVER_MAX;
            }
            break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_INT64:
            /* 检查64位有符号整数是否小于最小值 */
            if (pval->s64val < *pParam->unMinValuePtr.pInt64)
            {
                return COT_PARAM_CHECK_OVER_MIN;
            }
            /* 检查64位有符号整数是否大于最大值 */
            else if (pval->s64val > *pParam->unMaxValuePtr.pInt64)
            {
                return COT_PARAM_CHECK_OVER_MAX;
            }
            break;
    #endif
        case COT_PARAM_UINT8:
            /* 检查8位无符号整数是否小于最小值 */
            if (pval->u64val < *pParam->unMinValuePtr.pUint8)
            {
                return COT_PARAM_CHECK_OVER_MIN;
            }
            /* 检查8位无符号整数是否大于最大值 */
            else if (pval->u64val > *pParam->unMaxValuePtr.pUint8)
            {
                return COT_PARAM_CHECK_OVER_MAX;
            }
            break;

        case COT_PARAM_UINT16:
            /* 检查16位无符号整数是否小于最小值 */
            if (pval->u64val < *pParam->unMinValuePtr.pUint16)
            {
                return COT_PARAM_CHECK_OVER_MIN;
            }
            /* 检查16位无符号整数是否大于最大值 */
            else if (pval->u64val > *pParam->unMaxValuePtr.pUint16)
            {
                return COT_PARAM_CHECK_OVER_MAX;
            }
            break;

        case COT_PARAM_UINT32:
            /* 检查32位无符号整数是否小于最小值 */
            if (pval->u64val < *pParam->unMinValuePtr.pUint32)
            {
                return COT_PARAM_CHECK_OVER_MIN;
            }
            /* 检查32位无符号整数是否大于最大值 */
            else if (pval->u64val > *pParam->unMaxValuePtr.pUint32)
            {
                return COT_PARAM_CHECK_OVER_MAX;
            }
            break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_UINT64:
            /* 检查64位无符号整数是否小于最小值 */
            if (pval->u64val < *pParam->unMinValuePtr.pUint64)
            {
                return COT_PARAM_CHECK_OVER_MIN;
            }
            /* 检查64位无符号整数是否大于最大值 */
            else if (pval->u64val > *pParam->unMaxValuePtr.pUint64)
            {
                return COT_PARAM_CHECK_OVER_MAX;
            }
            break;
    #endif
        case COT_PARAM_FLOAT:
            /* 检查单精度浮点数是否小于最小值 */
            if (pval->fVal < *pParam->unMinValuePtr.pFloat)
            {
                return COT_PARAM_CHECK_OVER_MIN;
            }
            /* 检查单精度浮点数是否大于最大值 */
            else if (pval->fVal > *pParam->unMaxValuePtr.pFloat)
            {
                return COT_PARAM_CHECK_OVER_MAX;
            }
            break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_DOUBLE:
            /* 检查双精度浮点数是否小于最小值 */
            if (pval->fVal < *pParam->unMinValuePtr.pDouble)
            {
                return COT_PARAM_CHECK_OVER_MIN;
            }
            /* 检查双精度浮点数是否大于最大值 */
            else if (pval->fVal > *pParam->unMaxValuePtr.pDouble)
            {
                return COT_PARAM_CHECK_OVER_MAX;
            }
            break;
    #endif
    #if COT_PARAM_USE_STRING_TYPE
        case COT_PARAM_STRING:
            /* 检查字符串长度是否小于最小长度限制 */
            if (strlen(pval->str) < *pParam->unMinValuePtr.pStringLength)
            {
                return COT_PARAM_CHECK_OVER_MIN;
            }
            /* 检查字符串长度是否超过最大长度限制 */
            else if (strlen(pval->str) > *pParam->unMaxValuePtr.pStringLength)
            {
                return COT_PARAM_CHECK_OVER_MAX;
            }
            break;
    #endif
        default:
            break;
    }

    return COT_PARAM_CHECK_OK;
}

/**
 * @brief      校验参数值是否在有效范围内
 *
 * @param[in]  pParam    参数信息结构体指针
 * @param[in]  pval      待校验的参数值指针
 *
 * @note       根据参数类型将参数值转换为统一格式并进行范围校验
 *
 * @retval     COT_PARAM_CHECK_OK        校验成功
 * @retval     COT_PARAM_CHECK_OVER_MIN  小于最小值
 * @retval     COT_PARAM_CHECK_OVER_MAX  大于最大值
 */
static cotParamCheckRet_e ValidateRangeByVoid(const cotParamInfo_t *pParam, const void *pval)
{
    Value_u uValue;

    /* 清空联合体变量 */
    memset(&uValue, 0, sizeof(uValue));

    /* 根据参数类型进行类型转换 */
    switch (pParam->type)
    {
        case COT_PARAM_INT8:
            /* 转换为64位有符号整数 */
            uValue.s64val = *(COT_PARAM_INT8_T *)pval;
            break;

        case COT_PARAM_INT16:
            /* 转换为64位有符号整数 */
            uValue.s64val = *(COT_PARAM_INT16_T *)pval;
            break;

        case COT_PARAM_INT32:
            /* 转换为64位有符号整数 */
            uValue.s64val = *(COT_PARAM_INT32_T *)pval;
            break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_INT64:
            /* 直接使用64位有符号整数 */
            uValue.s64val = *(COT_PARAM_INT64_T *)pval;
            break;
    #endif
        case COT_PARAM_UINT8:
            /* 转换为64位无符号整数 */
            uValue.u64val = *(COT_PARAM_UINT8_T *)pval;
            break;

        case COT_PARAM_UINT16:
            /* 转换为64位无符号整数 */
            uValue.u64val = *(COT_PARAM_UINT16_T *)pval;
            break;

        case COT_PARAM_UINT32:
            /* 转换为64位无符号整数 */
            uValue.u64val = *(COT_PARAM_UINT32_T *)pval;
            break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_UINT64:
            /* 直接使用64位无符号整数 */
            uValue.u64val = *(COT_PARAM_UINT64_T *)pval;
            break;
    #endif
        case COT_PARAM_FLOAT:
            /* 转换为双精度浮点数 */
            uValue.fVal = *(COT_PARAM_FLOAT_T *)pval;
            break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_DOUBLE:
            /* 直接使用双精度浮点数 */
            uValue.fVal = *(COT_PARAM_DOUBLE_T *)pval;
            break;
    #endif
    #if COT_PARAM_USE_STRING_TYPE
        case COT_PARAM_STRING:
            /* 复制字符串，确保不超过最大长度 */
            memcpy(uValue.str, pval, strlen(pval) >= COT_PARAM_STRING_MAX_LENGTH ? COT_PARAM_STRING_MAX_LENGTH - 1 : strlen(pval));
            break;
    #endif
        default:
            return COT_PARAM_CHECK_OK;
    }

    /* 调用范围校验函数 */
    return ValidateRange(pParam, &uValue);
}

/**
 * @brief      校验当前参数值并进行处理
 *
 * @attention  字符串类型参数若设置了最长的长度，超长则会进行截断，但是小于最小长度时则不做处理
 * @attention  该函数不会执行自定义校验
 * @param      pParam    参数信息结构体指针，包含参数的当前值和范围信息
 * @param      eResetOpt 参数值超出范围时的处理选项，可选值:
 *                       - COT_PARAM_RESET_NONE: 不做处理
 *                       - COT_PARAM_RESET_DEF: 恢复为默认值
 *                       - COT_PARAM_RESET_MIN: 恢复为最小值
 *                       - COT_PARAM_RESET_MAX: 恢复为最大值
 *                       - COT_PARAM_RESET_MIN_MAX: 根据超出方向恢复为最小值或最大值
 *
 * @note       该函数执行参数值的校验和处理:
 *             1. 首先检查参数指针的有效性
 *             2. 调用ValidateRangeByVoid进行范围校验
 *             3. 如果校验失败，根据eResetOpt选项进行处理:
 *                - 可以选择恢复为默认值
 *                - 可以选择恢复为最小值或最大值
 *                - 可以根据超出方向自动选择恢复为最小值或最大值
 *             4. 不执行自定义校验函数
 *
 * @retval     0  成功
 * @retval     -1 失败
 */
int cotParam_SingleParamCheckProcess(const cotParamInfo_t *pParam, cotParamResetOpt_e eResetOpt)
{
    cotParamCheckRet_e eCheckResult;

    /* 参数有效性检查 */
    if (pParam == NULL)
    {
        return -1;
    }

    /* 执行参数范围检查 */
    eCheckResult = ValidateRangeByVoid(pParam, pParam->unCurValuePtr.pVoid);

    /* 如果参数超出范围，根据重置选项进行处理 */
    if (eCheckResult != COT_PARAM_CHECK_OK)
    {
        /* 重置为默认值 */
        if (eResetOpt == COT_PARAM_RESET_DEF)
        {
            ResetParamValue(pParam);
        }
        /* 重置为最小值：当指定重置为最小值，或者值小于最小值且指定了最大最小值重置 */
        else if (eResetOpt == COT_PARAM_RESET_MIN || (eResetOpt == COT_PARAM_RESET_MIN_MAX && eCheckResult == COT_PARAM_CHECK_OVER_MIN))
        {
            ResetParamMinValue(pParam);
        }
        /* 重置为最大值：当指定重置为最大值，或者值大于最大值且指定了最大最小值重置 */
        else if (eResetOpt == COT_PARAM_RESET_MAX || (eResetOpt == COT_PARAM_RESET_MIN_MAX && eCheckResult == COT_PARAM_CHECK_OVER_MAX))
        {
            ResetParamMaxValue(pParam);
        }
    }

    return 0;
}

/**
 * @brief      更新参数值同时进行校验处理
 *
 * @attention  该函数不会执行自定义校验
 * @param      pParam    参数信息结构体指针，包含参数的当前值和范围信息
 * @param      pNewValue 新的参数值指针，类型必须与参数类型匹配
 * @param      eResetOpt 新的参数值超出范围时的处理选项，可选值:
 *                       - COT_PARAM_RESET_NONE: 不做处理
 *                       - COT_PARAM_RESET_DEF: 恢复为默认值
 *                       - COT_PARAM_RESET_MIN: 恢复为最小值
 *                       - COT_PARAM_RESET_MAX: 恢复为最大值
 *                       - COT_PARAM_RESET_MIN_MAX: 根据超出方向恢复为最小值或最大值
 *
 * @note       该函数更新参数值并进行范围校验:
 *             1. 首先检查参数指针的有效性
 *             2. 调用ValidateRangeByVoid校验新值是否在有效范围内
 *             3. 如果校验失败，根据eResetOpt选项处理:
 *                - 可以选择恢复为默认值
 *                - 可以选择恢复为最小值或最大值
 *                - 可以根据超出方向自动选择恢复为最小值或最大值
 *             4. 如果校验通过，将新值复制到参数的当前值:
 *                - 对于字符串类型使用strcpy
 *                - 对于其他类型使用memcpy
 *
 * @retval     0  成功
 * @retval     -1 失败
 */
int cotParam_SingleParamUpdate(const cotParamInfo_t *pParam, const void *pNewValue, cotParamResetOpt_e eResetOpt)
{
    cotParamCheckRet_e eCheckResult;

    /* 参数有效性检查 */
    if (pParam == NULL)
    {
        return -1;
    }

    /* 检查新值是否在有效范围内 */
    eCheckResult = ValidateRangeByVoid(pParam, pNewValue);

    /* 如果新值超出范围，根据重置选项进行处理 */
    if (eCheckResult != COT_PARAM_CHECK_OK)
    {
        /* 重置为默认值 */
        if (eResetOpt == COT_PARAM_RESET_DEF)
        {
            ResetParamValue(pParam);
        }
        /* 重置为最小值：当指定重置为最小值，或者值小于最小值且指定了最大最小值重置 */
        else if (eResetOpt == COT_PARAM_RESET_MIN || (eResetOpt == COT_PARAM_RESET_MIN_MAX && eCheckResult == COT_PARAM_CHECK_OVER_MIN))
        {
            ResetParamMinValue(pParam);
        }
        /* 重置为最大值：当指定重置为最大值，或者值大于最大值且指定了最大最小值重置 */
        else if (eResetOpt == COT_PARAM_RESET_MAX || (eResetOpt == COT_PARAM_RESET_MIN_MAX && eCheckResult == COT_PARAM_CHECK_OVER_MAX))
        {
            ResetParamMaxValue(pParam);
        }
    }
    else
    {
#if COT_PARAM_USE_STRING_TYPE
        /* 根据参数类型选择不同的更新方式 */
        if (pParam->type != COT_PARAM_STRING)
        {
            /* 非字符串类型使用内存拷贝 */
            memcpy(pParam->unCurValuePtr.pVoid, pNewValue, pParam->length);
        }
        else
        {
            /* 字符串类型使用字符串拷贝 */
            strcpy(pParam->unCurValuePtr.pString, pNewValue);
        }
#else
        /* 不支持字符串类型时直接使用内存拷贝 */
        memcpy(pParam->unCurValuePtr.pVoid, pNewValue, pParam->length);
#endif
    }

    return 0;
}

/**
 * @brief      根据参数信息校验输入的值
 *
 * @param[in]  pParam        参数信息结构体指针
 * @param[in]  pValue        输入的参数值指针，类型需要与参数类型一致
 * @param[out] peCheckResult 校验结果
 *
 * @note       如果参数有自定义校验方式，则只有满足范围校验成功的前提下才会执行自定义校验
 *
 * @retval     0             成功
 * @retval     -1            失败
 */
int cotParam_SingleParamCheckInput(const cotParamInfo_t *pParam, const void *pValue, cotParamCheckRet_e *peCheckResult)
{
    /* 参数有效性检查 */
    if (pParam == NULL || pValue == NULL || peCheckResult == NULL)
    {
        return -1;
    }

    /* 执行参数范围检查 */
    *peCheckResult = ValidateRangeByVoid(pParam, pValue);

#if COT_PARAM_USE_CUSTOM_CHECK
    /* 如果范围检查通过且启用了自定义检查 */
    if (*peCheckResult == COT_PARAM_CHECK_OK)
    {
        /* 执行自定义参数检查 */
        if (pParam->pfnParamCheck != NULL)
        {
            if (pParam->pfnParamCheck(pValue) != 0)
            {
                /* 自定义检查失败 */
                *peCheckResult = COT_PARAM_CHECK_OTHER_ERR;
            }
        }
    }
#endif
    return 0;
}

/**
 * @brief      校验当前参数值
 *
 * @param[in]  pParam        参数信息结构体指针
 * @param[out] peCheckResult 校验结果
 *
 * @note       如果参数有自定义校验方式，则只有满足范围校验成功的前提下才会执行自定义校验
 *
 * @retval     0             成功
 * @retval     -1            失败
 */
int cotParam_SingleParamSelfCheck(const cotParamInfo_t *pParam, cotParamCheckRet_e *peCheckResult)
{
    /* 对参数当前值进行范围和自定义检查 */
    return cotParam_SingleParamCheckInput(pParam, pParam->unCurValuePtr.pVoid, peCheckResult);
}

/**
 * @brief      重置参数为缺省值
 *
 * @param[in]  pParam    参数信息结构体指针
 *
 * @note       无缺省值的参数会失败
 *
 * @retval     0         成功
 * @retval     -1        失败
 */
int cotParam_SingleParamResetDefValue(const cotParamInfo_t *pParam)
{
    /* 参数有效性检查 */
    if (pParam == NULL)
    {
        return -1;
    }

    /* 尝试重置参数为默认值，如果参数不支持重置则返回失败 */
    if (!ResetParamValue(pParam))
    {
        return -1;
    }

    return 0;
}

/**
 * @brief      重置参数为最小值
 *
 * @param[in]  pParam    参数信息结构体指针
 *
 * @note       字符串类型参数该功能无效, 无最大最小值的参数也会失败
 *
 * @retval     0         成功
 * @retval     -1        失败
 */
int cotParam_SingleParamResetMinValue(const cotParamInfo_t *pParam)
{
    /* 参数有效性检查 */
    if (pParam == NULL)
    {
        return -1;
    }

    /* 尝试重置参数为最小值，如果参数不支持范围限制则返回失败 */
    if (!ResetParamMinValue(pParam))
    {
        return -1;
    }

    return 0;
}

/**
 * @brief      重置参数为最大值
 *
 * @param[in]  pParam    参数信息结构体指针
 *
 * @note       字符串类型参数该功能无效, 无最大最小值的参数也会失败
 *
 * @retval     0         成功
 * @retval     -1        失败
 */
int cotParam_SingleParamResetMaxValue(const cotParamInfo_t *pParam)
{
    /* 参数有效性检查 */
    if (pParam == NULL)
    {
        return -1;
    }

    /* 尝试重置参数为最大值，如果参数不支持范围限制则返回失败 */
    if (!ResetParamMaxValue(pParam))
    {
        return -1;
    }

    return 0;
}

/**
 * @brief 从字节流中反序列化参数值
 *
 * @param[in,out] pParam    参数信息结构体指针，用于存储反序列化后的参数值
 * @param[in]     pbuf      包含序列化数据的字节流
 *
 * @note       根据参数类型从字节流中反序列化数据：
 *             - 对于整数类型，先反序列化为64位整数，再转换为目标类型
 *             - 对于浮点类型，直接调用对应的反序列化函数
 *             - 对于字符串类型，直接进行内存拷贝
 *
 * @retval     uint16_t     处理的字节数
 * @retval     0            参数类型不支持
 */
uint16_t ParamInfoFormStream(cotParamInfo_t *pParam, const uint8_t *pbuf)
{
    /* 根据参数类型选择相应的反序列化方法 */
    /* 该函数负责将字节流数据反序列化为参数值 */
    /* 对于每种参数类型，使用相应的反序列化函数进行处理 */
    /* 整数类型先反序列化为64位，再转换为目标类型以保证精度 */
    switch (pParam->type)
    {
        case COT_PARAM_INT8:
        {
            int64_t val = 0;
            /* 先反序列化为64位整数，确保不丢失精度 */
            pbuf = UnSerializeInt(pbuf, &val, pParam->length);
            /* 将64位整数值转换为目标8位整数类型 */
            *pParam->unCurValuePtr.pInt8 = (COT_PARAM_INT8_T)val;
        }
        break;

        case COT_PARAM_INT16:
        {
            int64_t val = 0;
            /* 反序列化为64位整数 */
            pbuf = UnSerializeInt(pbuf, &val, pParam->length);
            /* 转换为16位整数 */
            *pParam->unCurValuePtr.pInt16 = (COT_PARAM_INT16_T)val;
        }
        break;

        case COT_PARAM_INT32:
        {
            int64_t val = 0;
            /* 反序列化为64位整数 */
            pbuf = UnSerializeInt(pbuf, &val, pParam->length);
            /* 转换为32位整数 */
            *pParam->unCurValuePtr.pInt32 = (COT_PARAM_INT32_T)val;
        }
        break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_INT64:
        {
            int64_t val = 0;
            /* 直接反序列化为64位整数 */
            pbuf = UnSerializeInt(pbuf, &val, pParam->length);
            /* 赋值给目标变量 */
            *pParam->unCurValuePtr.pInt64 = (COT_PARAM_INT64_T)val;
        }
        break;
    #endif
        case COT_PARAM_UINT8:
        {
            uint64_t val = 0;
            /* 反序列化为64位无符号整数 */
            pbuf = UnSerializeUint(pbuf, &val, pParam->length);
            /* 转换为8位无符号整数 */
            *pParam->unCurValuePtr.pUint8 = (COT_PARAM_UINT8_T)val;
        }
        break;

        case COT_PARAM_UINT16:
        {
            uint64_t val = 0;
            /* 反序列化为64位无符号整数 */
            pbuf = UnSerializeUint(pbuf, &val, pParam->length);
            /* 转换为16位无符号整数 */
            *pParam->unCurValuePtr.pUint16 = (COT_PARAM_UINT16_T)val;
        }
        break;

        case COT_PARAM_UINT32:
        {
            uint64_t val = 0;
            /* 反序列化为64位无符号整数 */
            pbuf = UnSerializeUint(pbuf, &val, pParam->length);
            /* 转换为32位无符号整数 */
            *pParam->unCurValuePtr.pUint32 = (COT_PARAM_UINT32_T)val;
        }
        break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_UINT64:
        {
            uint64_t val = 0;
            /* 直接反序列化为64位无符号整数 */
            pbuf = UnSerializeUint(pbuf, &val, pParam->length);
            /* 赋值给目标变量 */
            *pParam->unCurValuePtr.pUint64 = (COT_PARAM_UINT64_T)val;
        }
        break;
    #endif
        case COT_PARAM_FLOAT:
            /* 反序列化为单精度浮点数 */
            pbuf = UnSerializeFloat(pbuf, pParam->unCurValuePtr.pFloat);
            break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_DOUBLE:
            /* 反序列化为双精度浮点数 */
            pbuf = UnSerializeDouble(pbuf, pParam->unCurValuePtr.pDouble);
            break;
    #endif
    #if COT_PARAM_USE_STRING_TYPE
        case COT_PARAM_STRING:
            /* 字符串类型直接进行内存拷贝 */
            memcpy(pParam->unCurValuePtr.pString, &pbuf[0], pParam->length);
            break;
    #endif
        default:
            return 0; /*不支持的参数类型 */
    }

    /* 返回处理的字节数 */
    return pParam->length;
}

/**
 * @brief      将缓冲区数据向前移动
 *
 * @param[in]  pbuf      缓冲区指针，指向待移动数据的起始位置
 * @param[in]  length    需要移动的数据长度，单位为字节
 *
 * @note       将缓冲区中的数据向前移动指定长度，用于处理参数数据流的连续读取。
 *             使用memmove函数确保源和目标区域重叠时的正确性。
 *
 * @retval     uint8_t*  返回移动后的缓冲区指针，即pbuf - length
 */
static uint8_t *MoveBufToBase(uint8_t *pbuf, uint32_t length)
{
    /* 将数据向前移动length个字节 */
    memmove(pbuf - length, pbuf, length);
    return (pbuf - length);
}

/**
 * @brief      从存储介质加载参数数据
 *
 * @param[in]  pManager        参数管理器句柄
 * @param[in]  pfnLoadCallback 数据加载回调函数，用于从存储介质读取数据
 *
 * @note       该函数实现参数数据的加载过程：
 *             1. 分配临时缓冲区用于存储加载的数据
 *             2. 循环调用加载回调函数读取数据
 *             3. 对于键值对模式：
 *                - 首先读取支持的键长度
 *                - 解析键值获取参数ID和长度
 *                - 查找对应的参数并进行反序列化
 *             4. 对于连续模式：
 *                - 按参数表顺序依次反序列化数据
 *
 * @retval     0               加载成功
 * @retval     -1              参数无效
 * @retval     -2              加载回调执行失败
 */
int cotParam_Load(const cotParamManager_t *pManager, cotParamLoad_f pfnLoadCallback)
{
    /* 分配缓冲区，如果支持字符串类型则需要额外的空间 */
    /* 缓冲区大小根据是否支持字符串类型动态调整 */
    /* 字符串类型需要额外的COT_PARAM_STRING_MAX_LENGTH字节空间 */
#if COT_PARAM_USE_STRING_TYPE
    uint8_t buf[sizeof(cotParamInfo_t) + COT_PARAM_STRING_MAX_LENGTH];
#else
    uint8_t buf[sizeof(cotParamInfo_t)];
#endif
    uint8_t *ptr = buf;

    /* 参数有效性检查 */
    /* 确保参数管理器和回调函数指针都有效 */
    if (pManager == NULL || pfnLoadCallback == NULL)
    {
        return -1;
    }

    /* 初始化参数加载过程中需要的变量 */
    uint16_t length = 0;        /* 当前缓冲区中的数据长度 */
    uint16_t paramLength = 0;   /* 单个参数的数据长度 */
    uint16_t id = 0;            /* 参数ID */
    cotParamInfo_t *pParamInfo; /* 参数信息结构体指针 */
    uint8_t keyLength = 0;      /* 键值对模式下的键长度 */
#if COT_PARAM_USE_KEY_VALUE
    uint64_t key = 0; /* 键值对模式下的完整键值 */
#endif

    /* 循环读取并处理参数数据 */
    /* 通过回调函数分批次读取参数数据 */
    /* 每次读取尽可能多的数据填充缓冲区 */
    do
    {
        /* 计算剩余可用缓冲区大小 */
        /* 确保不会发生缓冲区溢出 */
        length = sizeof(buf) - (ptr - buf);

        /* 调用回调函数读取数据 */
        /* 如果读取失败则返回错误码 */
        if (pfnLoadCallback(ptr, length, &length) != 0)
        {
            return -2;
        }

        /* 如果没有读取到数据，表示已经完成所有参数的加载 */
        if (length == 0)
        {
            break;
        }

        /* 更新实际数据长度并重置缓冲区指针 */
        length += (ptr - buf);
        ptr = buf;

#if COT_PARAM_USE_KEY_VALUE
        /* 第一次读取时获取键长度信息 */
        /* 键长度信息存储在数据流的第一个字节中 */
        if (keyLength == 0)
        {
            keyLength = ptr[0]; /* 读取键长度 */
            ptr++;              /* 移动指针跳过键长度字节 */
            length -= 1;        /* 更新剩余数据长度 */
        }

        /* 处理键值对格式的参数数据 */
        /* 每个参数由键和值两部分组成 */
        while (length > keyLength)
        {
            /* 从数据流中解析键值 */
            UnSerializeUint(ptr, &key, keyLength);

            /* 根据不同的支持范围解析参数ID和长度 */
#if COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_16
            id = (key >> 4) & 0x0F;   /* 取高4位作为ID */
            paramLength = key & 0x0F; /* 取低4位作为长度 */
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_256
            id = (key >> 8) & 0xFF;   /* 取高8位作为ID */
            paramLength = key & 0xFF; /* 取低8位作为长度 */
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_4096
            id = (key >> 12) & 0xFFF;  /* 取高12位作为ID */
            paramLength = key & 0xFFF; /* 取低12位作为长度 */
#endif

            /* 检查剩余数据是否足够读取完整参数 */
            if (length < (paramLength + keyLength))
            {
                break; /* 数据不足，等待下次读取 */
            }

            /* 跳过键值数据 */
            ptr += keyLength;
            length -= keyLength;

            /* 根据ID查找参数信息 */
            pParamInfo = (cotParamInfo_t *)FindParamByID(pManager, id);

            /* 验证参数信息和长度是否匹配 */
            /* 如果参数不存在或长度不匹配，跳过该参数数据 */
            if (pParamInfo == NULL || paramLength != pParamInfo->length)
            {
                ptr += paramLength;
                length -= paramLength;
                continue;
            }

            ParamInfoFormStream(pParamInfo, ptr);
            ptr += paramLength;
            length -= paramLength;
        }

#else
        /* 非键值对模式下的参数加载 */
        /* 参数按固定顺序存储，通过索引直接访问 */
        while (length >= 1)
        {
            /* 获取当前索引对应的参数信息 */
            pParamInfo = &pManager->pParamTable[id];

            /* 检查剩余数据是否足够读取完整参数 */
            if (length < pParamInfo->length)
            {
                break; /* 数据不足，等待下次读取 */
            }

            /* 反序列化参数值 */
            ParamInfoFormStream(pParamInfo, ptr);
            /* 更新指针和长度 */
            ptr += pParamInfo->length;
            length -= pParamInfo->length;
            id++; /* 处理下一个参数 */
        }

#endif
        ptr = MoveBufToBase(ptr, ptr - buf);
        ptr += length;
    } while (1);

    return 0;
}

/**
 * @brief      将参数值序列化为字节流
 *
 * @param[out] pbuf    用于存储序列化数据的缓冲区
 * @param[in]  pParam  参数信息结构体指针
 *
 * @note       该函数根据参数类型将数据序列化为字节流：
 *             1. 对于整数类型，调用SerializeInt或SerializeUint函数进行序列化
 *             2. 对于浮点类型，调用SerializeFloat或SerializeDouble函数进行序列化
 *             3. 对于字符串类型，直接进行内存拷贝
 *             4. 所有数值类型都采用小端序存储
 *
 * @retval     uint16_t 返回序列化后的字节数，如果参数类型不支持则返回0
 */
uint16_t ParamInfoToStream(uint8_t *pbuf, cotParamInfo_t *pParam)
{
    /* 参数有效性检查 */
    if (pbuf == NULL || pParam == NULL)
    {
        return 0;
    }

    /* 根据参数类型选择相应的序列化方法 */
    switch (pParam->type)
    {
        case COT_PARAM_INT8:
            /* 将8位有符号整数序列化为字节流 */
            pbuf = SerializeInt(pbuf, *(COT_PARAM_INT8_T *)pParam->unCurValuePtr.pVoid, pParam->length);
            break;

        case COT_PARAM_INT16:
            /* 将16位有符号整数序列化为字节流 */
            pbuf = SerializeInt(pbuf, *(COT_PARAM_INT16_T *)pParam->unCurValuePtr.pVoid, pParam->length);
            break;

        case COT_PARAM_INT32:
            /* 将32位有符号整数序列化为字节流 */
            pbuf = SerializeInt(pbuf, *(COT_PARAM_INT32_T *)pParam->unCurValuePtr.pVoid, pParam->length);
            break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_INT64:
            /* 将64位有符号整数序列化为字节流 */
            pbuf = SerializeInt(pbuf, *(COT_PARAM_INT64_T *)pParam->unCurValuePtr.pVoid, pParam->length);
            break;
    #endif
        case COT_PARAM_UINT8:
            /* 将8位无符号整数序列化为字节流 */
            pbuf = SerializeUint(pbuf, *(COT_PARAM_UINT8_T *)pParam->unCurValuePtr.pVoid, pParam->length);
            break;

        case COT_PARAM_UINT16:
            /* 将16位无符号整数序列化为字节流 */
            pbuf = SerializeUint(pbuf, *(COT_PARAM_UINT16_T *)pParam->unCurValuePtr.pVoid, pParam->length);
            break;

        case COT_PARAM_UINT32:
            /* 将32位无符号整数序列化为字节流 */
            pbuf = SerializeUint(pbuf, *(COT_PARAM_UINT32_T *)pParam->unCurValuePtr.pVoid, pParam->length);
            break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_UINT64:
            /* 将64位无符号整数序列化为字节流 */
            pbuf = SerializeUint(pbuf, *(COT_PARAM_UINT64_T *)pParam->unCurValuePtr.pVoid, pParam->length);
            break;
    #endif
        case COT_PARAM_FLOAT:
            /* 将单精度浮点数序列化为字节流 */
            pbuf = SerializeFloat(pbuf, *(COT_PARAM_FLOAT_T *)pParam->unCurValuePtr.pVoid);
            break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_DOUBLE:
            /* 将双精度浮点数序列化为字节流 */
            pbuf = SerializeDouble(pbuf, *(COT_PARAM_DOUBLE_T *)pParam->unCurValuePtr.pVoid);
            break;
    #endif
    #if COT_PARAM_USE_STRING_TYPE
        case COT_PARAM_STRING:
            /* 字符串类型直接进行内存拷贝 */
            memcpy(&pbuf[0], pParam->unCurValuePtr.pString, pParam->length);
            break;
    #endif
        default:
            return 0; /* 不支持的参数类型 */
    }

    /* 返回序列化后的字节数 */
    return pParam->length;
}

/**
 * @brief 将参数数据保存到存储介质
 *
 * @param[in]  pManager        参数管理器句柄
 * @param[in]  pfnSaveCallback 数据保存回调函数，用于将数据写入存储介质
 *
 * @note       该函数实现参数数据的保存过程：
 *             1. 分配临时缓冲区用于存储序列化数据
 *             2. 对于键值对模式：
 *                - 首先写入支持的键长度
 *                - 对每个参数生成键值（包含ID和长度）
 *                - 序列化参数数据并写入存储介质
 *             3. 对于连续模式：
 *                - 直接序列化参数数据并写入
 *             4. 最后写入长度为0的数据表示结束
 *
 * @retval     0               保存成功
 * @retval     -1              参数无效
 * @retval     -2              保存回调执行失败
 */
int cotParam_Save(const cotParamManager_t *pManager, cotParamSave_f pfnSaveCallback)
{
    /* 分配缓冲区，如果支持字符串类型则需要额外的空间 */
#if COT_PARAM_USE_STRING_TYPE
    uint8_t buf[sizeof(cotParamInfo_t) + COT_PARAM_STRING_MAX_LENGTH];
#else
    uint8_t buf[sizeof(cotParamInfo_t)];
#endif
    uint8_t *ptr = buf;
    uint16_t length = 0;
#if COT_PARAM_USE_KEY_VALUE
    uint64_t key = 0;
#endif

    /* 参数有效性检查 */
    if (pManager == NULL || pfnSaveCallback == NULL)
    {
        return -1;
    }

#if COT_PARAM_USE_KEY_VALUE
    buf[0] = COT_PARAM_SUPPORT_NUM;

    if (pfnSaveCallback(buf, 1) != 0)
    {
        return -2;
    }
#endif

    /* 遍历参数表，序列化每个参数 */
    for (int i = 0; i < pManager->count; i++)
    {
        /* 重置缓冲区指针和长度计数器 */
        ptr = buf;
        length = 0;
#if COT_PARAM_USE_KEY_VALUE
        /* 根据不同的支持数目格式，构造参数ID和长度的组合键值 */
#if COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_16
        key = (pManager->pParamTable[i].id << 4) | (pManager->pParamTable[i].length & 0x0F);
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_256
        key = (pManager->pParamTable[i].id << 8) | (pManager->pParamTable[i].length & 0xFF);
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_4096
        key = (pManager->pParamTable[i].id << 12) | (pManager->pParamTable[i].length & 0xFFF);
#endif
        ptr = SerializeUint(ptr, key, COT_PARAM_SUPPORT_NUM);
        length += COT_PARAM_SUPPORT_NUM;
#endif
        length = ParamInfoToStream(&buf[length], &pManager->pParamTable[i]);
        ptr += length;

        if (pfnSaveCallback(buf, (ptr - buf)) != 0)
        {
            return -2;
        }
    }

    if (pfnSaveCallback(buf, 0) != 0)
    {
        return -2;
    }

    return 0;
}

/**
 * @brief 计算参数序列化后的总字节数
 *
 * @param[in]  pManager   参数管理器句柄
 *
 * @note       该函数计算所有参数序列化后的总大小：
 *             1. 初始长度为1（用于存储键长度）
 *             2. 遍历参数表累加每个参数的长度：
 *                - 键值对模式：参数长度 + 键长度
 *                - 连续模式：仅参数长度
 *
 * @retval     >0         序列化大小（字节数）
 * @retval     0          参数无效
 */
uint32_t cotParam_GetSerializeSize(const cotParamManager_t *pManager)
{
    /* 初始化序列化大小计数器，预留1字节用于存储支持数目 */
    uint32_t length = 1;
    uint16_t idx = 0;

    /* 参数有效性检查 */
    if (pManager == NULL)
    {
        return 0;
    }

    /* 遍历参数表计算总序列化大小 */
    while (idx < pManager->count)
    {
#if COT_PARAM_USE_KEY_VALUE
        /* 键值对模式：每个参数需要额外的键长度空间 */
        length += (pManager->pParamTable[idx++].length + COT_PARAM_SUPPORT_NUM);
#else
        /* 普通模式：只需要参数值的长度 */
        length += pManager->pParamTable[idx++].length;
#endif
    }

    return length;
}

/**
 * @brief 将参数表中的参数序列化为字节流
 *
 * @param[in]  pManager   参数管理器句柄
 * @param[out] pbuf       序列化数据的输出缓冲区
 *
 * @note       该函数实现参数表的序列化：
 *             1. 首先进行参数有效性检查
 *             2. 如果启用了键值对模式(COT_PARAM_USE_KEY_VALUE)：
 *                - 在缓冲区开头写入支持的参数数量
 *                - 对每个参数，先序列化其ID和长度信息
 *             3. 遍历参数表中的每个参数：
 *                - 在键值对模式下，将参数ID和长度编码为key
 *                - 调用ParamInfoToStream将参数值序列化到缓冲区
 *             4. 返回序列化后的总数据长度
 *
 * @retval     uint32_t   序列化后的数据长度（字节数）
 */
uint32_t cotParam_Serialize(const cotParamManager_t *pManager, uint8_t *pbuf)
{
    /* 参数有效性检查 */
    if (pManager == NULL)
    {
        return 0;
    }

    /* 初始化序列化缓冲区指针 */
    uint8_t *ptr = pbuf;
#if COT_PARAM_USE_KEY_VALUE
    uint64_t key = 0;

    /* 写入支持的参数数量作为头部信息 */
    *ptr = COT_PARAM_SUPPORT_NUM;
    ptr++;
#endif

    /* 遍历参数表，序列化每个参数 */
    for (int i = 0; i < pManager->count; i++)
    {
#if COT_PARAM_USE_KEY_VALUE
        /* 根据不同的支持数量，计算参数ID和长度的组合键值 */
#if COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_16
        /* 4位ID + 4位长度 */
        key = (pManager->pParamTable[i].id << 4) | (pManager->pParamTable[i].length & 0x0F);
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_256
        /* 8位ID + 8位长度 */
        key = (pManager->pParamTable[i].id << 8) | (pManager->pParamTable[i].length & 0xFF);
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_4096
        /* 12位ID + 12位长度 */
        key = (pManager->pParamTable[i].id << 12) | (pManager->pParamTable[i].length & 0xFFF);
#endif
        /* 序列化键值 */
        ptr = SerializeUint(ptr, key, COT_PARAM_SUPPORT_NUM);
#endif
        /* 序列化参数值 */
        ptr += ParamInfoToStream(ptr, &pManager->pParamTable[i]);
    }

    /* 返回序列化后的总字节数 */
    return ptr - pbuf;
}

/**
 * @brief      从字节流中反序列化参数值
 *
 * @param[in]  pManager   参数管理器句柄
 * @param[in]  pbuf       包含序列化数据的输入缓冲区
 * @param[in]  length     输入缓冲区的长度
 *
 * @note       该函数实现参数的反序列化：
 *             1. 首先进行参数有效性检查
 *             2. 在键值对模式下(COT_PARAM_USE_KEY_VALUE)：
 *                - 读取键长度信息
 *                - 循环解析每个参数的键值对：
 *                  a) 解析键信息得到参数ID和长度
 *                  b) 查找对应的参数信息
 *                  c) 验证参数长度是否匹配
 *                  d) 调用ParamInfoFormStream恢复参数值
 *             3. 在非键值对模式下：
 *                - 按顺序读取每个参数的值
 *                - 直接调用ParamInfoFormStream恢复参数值
 *             4. 处理过程中进行缓冲区边界检查
 *
 * @retval     0          成功
 * @retval     -1         失败
 */
int cotParam_Deserialization(const cotParamManager_t *pManager, const uint8_t *pbuf, uint32_t length)
{
    /* 参数有效性检查 */
    if (pManager == NULL)
    {
        return -1;
    }

    /* 初始化反序列化指针和变量 */
    const uint8_t *ptr = pbuf;
    uint16_t id = 0;
    cotParamInfo_t *pParamInfo;

#if COT_PARAM_USE_KEY_VALUE
    /* 键值模式下的额外变量 */
    uint8_t keyLength = 0;    /* 键的长度 */
    uint16_t paramLength = 0; /* 参数值的长度 */
    uint64_t key = 0;         /* 键值 */

    /* 读取键长度信息 */
    if (keyLength == 0)
    {
        keyLength = ptr[0];
        ptr++;
        length -= 1;
    }

    /* 循环解析键值对格式的参数数据 */
    while (length > keyLength)
    {
        /* 从字节流中解析键值 */
        ptr = UnSerializeUint(ptr, &key, keyLength);

        /* 根据不同的支持数量，从键值中提取参数ID和长度 */
#if COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_16
        /* 4位ID + 4位长度 */
        id = (key >> 4) & 0x0F;
        paramLength = key & 0x0F;
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_256
        /* 8位ID + 8位长度 */
        id = (key >> 8) & 0xFF;
        paramLength = key & 0xFF;
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_4096
        /* 12位ID + 12位长度 */
        id = (key >> 12) & 0xFFF;
        paramLength = key & 0xFFF;
#endif

        /* 检查剩余数据是否足够 */
        if (length < (paramLength + keyLength))
        {
            break;
        }

        /* 更新剩余长度 */
        length -= (keyLength + paramLength);

        /* 查找参数信息 */
        pParamInfo = (cotParamInfo_t *)FindParamByID(pManager, id);

        /* 参数有效性验证 */
        if (pParamInfo == NULL || paramLength != pParamInfo->length)
        {
            ptr += paramLength;
            continue;
        }

        /* 从字节流恢复参数值 */
        ParamInfoFormStream(pParamInfo, ptr);
        ptr += paramLength;
    }

#else
    /* 顺序格式的参数数据解析 */
    while (length >= 1)
    {
        /* 获取当前参数信息 */
        pParamInfo = &pManager->pParamTable[id];

        /* 检查剩余数据是否足够 */
        if (length < pParamInfo->length)
        {
            break;
        }

        /* 从字节流恢复参数值 */
        ParamInfoFormStream(pParamInfo, ptr);
        ptr += pParamInfo->length;
        length -= pParamInfo->length;
        id++;
    }
#endif

    return 0;
}

/**
 * @brief      实现单个参数值的修改
 *
 * @param[in]  pManager   参数管理器句柄
 * @param[in]  pCurParam  要修改的参数当前值的指针
 * @param[in]  paramList  包含新参数值的可变参数列表
 *
 * @note       该函数主要是方便进行二次函数封装，隐藏参数表管理句柄入参，可参考 cotParam_SingleParamChange 的实现。
 *             根据参数类型从可变参数列表中获取新值并进行相应处理。
 *
 * @retval     0          成功
 * @retval     -1         失败
 */
int cotParam_SingleParamChangeImpl(const cotParamManager_t *pManager, const void *pCurParam, va_list paramList)
{
    /* 根据参数指针查找参数信息 */
    const cotParamInfo_t *pParam = cotParam_FindParamByParamPtr(pManager, pCurParam);

    /* 参数有效性检查 */
    if (pParam == NULL)
    {
        return -1;
    }

    /* 根据参数类型进行相应的值更新处理 */
    switch (pParam->type)
    {
        case COT_PARAM_INT8:
        {
            /* 8位有符号整数处理：从可变参数列表读取32位整数并转换为8位 */
            /* 注意：由于C语言可变参数传递规则，小于int的类型会被提升为int */
            COT_PARAM_INT8_T val = (COT_PARAM_INT8_T)va_arg(paramList, COT_PARAM_INT32_T);
            /* 更新参数值，不设置超范围处理选项 */
            cotParam_SingleParamUpdate(pParam, &val, COT_PARAM_RESET_NONE);
        }
        break;

        case COT_PARAM_INT16:
        {
            /* 16位有符号整数处理：从可变参数列表读取32位整数并转换为16位 */
            COT_PARAM_INT16_T val = (COT_PARAM_INT16_T)va_arg(paramList, COT_PARAM_INT32_T);
            /* 更新参数值，不设置超范围处理选项 */
            cotParam_SingleParamUpdate(pParam, &val, COT_PARAM_RESET_NONE);
        }
        break;

        case COT_PARAM_INT32:
        {
            /* 32位有符号整数处理：直接从可变参数列表读取32位整数 */
            COT_PARAM_INT32_T val = (COT_PARAM_INT32_T)va_arg(paramList, COT_PARAM_INT32_T);
            /* 更新参数值，不设置超范围处理选项 */
            cotParam_SingleParamUpdate(pParam, &val, COT_PARAM_RESET_NONE);
        }
        break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_INT64:
        {
            /* 64位有符号整数处理：直接从可变参数列表读取64位整数 */
            COT_PARAM_INT64_T val = (COT_PARAM_INT64_T)va_arg(paramList, COT_PARAM_INT64_T);
            /* 更新参数值，不设置超范围处理选项 */
            cotParam_SingleParamUpdate(pParam, &val, COT_PARAM_RESET_NONE);
        }
        break;
    #endif
        case COT_PARAM_UINT8:
        {
            /* 8位无符号整数处理：从可变参数列表读取32位无符号整数并转换为8位 */
            /* 注意：由于C语言可变参数传递规则，小于unsigned int的类型会被提升为unsigned int */
            COT_PARAM_UINT8_T val = (COT_PARAM_UINT8_T)va_arg(paramList, COT_PARAM_UINT32_T);
            /* 更新参数值，不设置超范围处理选项 */
            cotParam_SingleParamUpdate(pParam, &val, COT_PARAM_RESET_NONE);
        }
        break;

        case COT_PARAM_UINT16:
        {
            /* 16位无符号整数处理：从可变参数列表读取32位无符号整数并转换为16位 */
            COT_PARAM_UINT16_T val = (COT_PARAM_UINT16_T)va_arg(paramList, COT_PARAM_UINT32_T);
            /* 更新参数值，不设置超范围处理选项 */
            cotParam_SingleParamUpdate(pParam, &val, COT_PARAM_RESET_NONE);
        }
        break;

        case COT_PARAM_UINT32:
        {
            /* 32位无符号整数处理：直接从可变参数列表读取32位无符号整数 */
            COT_PARAM_UINT32_T val = (COT_PARAM_UINT32_T)va_arg(paramList, COT_PARAM_UINT32_T);
            /* 更新参数值，不设置超范围处理选项 */
            cotParam_SingleParamUpdate(pParam, &val, COT_PARAM_RESET_NONE);
        }
        break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_UINT64:
        {
            /* 64位无符号整数处理：直接从可变参数列表读取64位无符号整数 */
            COT_PARAM_UINT64_T val = (COT_PARAM_UINT64_T)va_arg(paramList, COT_PARAM_UINT64_T);
            /* 更新参数值，不设置超范围处理选项 */
            cotParam_SingleParamUpdate(pParam, &val, COT_PARAM_RESET_NONE);
        }
        break;
    #endif
        case COT_PARAM_FLOAT:
        {
            /* 单精度浮点数处理：从可变参数列表读取双精度浮点数并转换为单精度 */
            /* 注意：由于C语言可变参数传递规则，float类型会被提升为double */
            COT_PARAM_FLOAT_T val = (COT_PARAM_FLOAT_T)va_arg(paramList, COT_PARAM_DOUBLE_T);
            /* 更新参数值，不设置超范围处理选项 */
            cotParam_SingleParamUpdate(pParam, &val, COT_PARAM_RESET_NONE);
        }
        break;
    #if COT_PARAM_USE_64_BIT_LENGTH
        case COT_PARAM_DOUBLE:
        {
            /* 双精度浮点数处理：直接从可变参数列表读取双精度浮点数 */
            COT_PARAM_DOUBLE_T val = (COT_PARAM_DOUBLE_T)va_arg(paramList, COT_PARAM_DOUBLE_T);
            /* 更新参数值，不设置超范围处理选项 */
            cotParam_SingleParamUpdate(pParam, &val, COT_PARAM_RESET_NONE);
        }
        break;
    #endif
    #if COT_PARAM_USE_STRING_TYPE
        case COT_PARAM_STRING:
        {
            /* 字符串类型处理：从可变参数列表获取字符串指针 */
            char *pszString = (char *)va_arg(paramList, char *);
            /* 创建临时缓冲区用于存储截断后的字符串 */
            char szString[COT_PARAM_STRING_MAX_LENGTH] = {0};

            /* 复制字符串，确保不超过最大长度限制 */
            /* 如果源字符串长度超过最大长度，则截断到最大长度减1（为结束符预留空间） */
            memcpy(szString, pszString, strlen(pszString) >= COT_PARAM_STRING_MAX_LENGTH ? (COT_PARAM_STRING_MAX_LENGTH - 1) : strlen(pszString));
            /* 更新参数值，不设置超范围处理选项 */
            cotParam_SingleParamUpdate(pParam, szString, COT_PARAM_RESET_NONE);
        }
        break;
    #endif
        default:
            /* 不支持的参数类型，返回错误 */
            return -1;
    }

    /* 参数更新成功 */
    return 0;
}

/**
 * @brief      修改单个参数的值，新值校验不通过则不修改
 *
 * @param[in]  pManager   参数管理器句柄
 * @param[in]  pCurParam  要修改的参数当前值的指针
 * @param[in]  ...        新的参数值
 *
 * @note       该函数是参数修改的入口函数：
 *             1. 使用可变参数方式接收新的参数值
 *             2. 初始化可变参数列表
 *             3. 调用cotParam_SingleParamChangeImpl执行实际的参数修改
 *             4. 清理可变参数列表
 *
 * @code       如：cotParam_SingleParamChange(&sg_tParamManager, &g_test_u16, 60)
 *
 * @retval     0          成功
 * @retval     -1         失败
 */
int cotParam_SingleParamChange(const cotParamManager_t *pManager, const void *pCurParam, ...)
{
    int ret = 0;
    va_list paramList;

    /* 初始化可变参数列表，从pCurParam参数开始 */
    va_start(paramList, pCurParam);

    /* 调用实际的参数更新实现函数 */
    ret = cotParam_SingleParamChangeImpl(pManager, pCurParam, paramList);

    /* 清理可变参数列表 */
    va_end(paramList);

    return ret;
}

/**
 * @brief 参数属性宏
 * @param x 参数属性值
 * @return 参数属性字符串
 * @details 根据参数的读写属性返回对应的字符串标识
 */
#define ATTR(x) ((x & (PARAM_ATTR_READ | COT_PARAM_ATTR_WRITE)) == (PARAM_ATTR_READ | COT_PARAM_ATTR_WRITE) ? "wr" : (x & (PARAM_ATTR_READ) ? "r" : ((x & (PARAM_ATTR_WRITE) ? "w" : ""))))

/**
 * @brief 获取参数属性字符串
 * @param attr 参数属性值
 * @return 参数属性字符串
 * @details 根据参数的属性位返回对应的字符串标识
 *          r: 可读
 *          w: 可写
 *          s: 可重置
 *          m: 有范围限制
 */
char *Attr(uint8_t attr)
{
    static char buf[10];
    char *p = buf;

    if (attr & COT_PARAM_ATTR_READ)
    {
        p += sprintf(p, "r");
    }

    if (attr & COT_PARAM_ATTR_WRITE)
    {
        p += sprintf(p, "w");
    }

    if (attr & COT_PARAM_ATTR_RESET)
    {
        p += sprintf(p, "s");
    }

    if (attr & COT_PARAM_ATTR_RANGE)
    {
        p += sprintf(p, "m");
    }

    return buf;
}

/**
 * @brief 显示单个参数的详细信息
 * @param paramInfo 参数信息结构体指针
 * @details 根据参数类型显示参数的各项属性，包括：
 *          - 参数ID
 *          - 参数名称
 *          - 参数类型
 *          - 参数长度
 *          - 参数属性（读/写/重置/范围）
 *          - 当前值
 *          - 默认值（如果支持重置）
 *          - 最小值和最大值（如果有范围限制）
 */
void ShowSingleParam(const cotParamInfo_t *paramInfo)
{
    /* 检查参数指针的有效性 */
    if (paramInfo != NULL)
    {
        /* 根据参数类型选择不同的显示格式 */
        switch (paramInfo->type)
        {
            /* 8位有符号整型参数显示处理 */
            case COT_PARAM_INT8:
                printf(" %-4d   %-24s %-10s %-6d %-8s %-10d ", paramInfo->id, paramInfo->name.pTextString,
                    "int8_t", paramInfo->length, Attr(paramInfo->attr), *paramInfo->unCurValuePtr.pInt8);

                /* 如果参数支持重置功能，显示默认值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RESET)
                    printf("%-10d ", *paramInfo->unDefValuePtr.pInt8);
                else
                    printf("%-10s ", "-");

                /* 如果参数有范围限制，显示最小值和最大值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RANGE)
                {
                    printf("%-10d ", *paramInfo->unMinValuePtr.pInt8);
                    printf("%-10d ", *paramInfo->unMaxValuePtr.pInt8);
                }
                else
                {
                    printf("%-10s ", "-");
                    printf("%-10s ", "-");
                }
                break;
            /* 16位有符号整型参数显示处理 */
            case COT_PARAM_INT16:
                printf(" %-4d   %-24s %-10s %-6d %-8s %-10d ", paramInfo->id, paramInfo->name.pTextString,
                    "int16_t", paramInfo->length, Attr(paramInfo->attr), *paramInfo->unCurValuePtr.pInt16);

                /* 如果参数支持重置功能，显示默认值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RESET)
                    printf("%-10d ", *paramInfo->unDefValuePtr.pInt16);
                else
                    printf("%-10s ", "-");

                /* 如果参数有范围限制，显示最小值和最大值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RANGE)
                {
                    printf("%-10d ", *paramInfo->unMinValuePtr.pInt16);
                    printf("%-10d ", *paramInfo->unMaxValuePtr.pInt16);
                }
                else
                {
                    printf("%-10s ", "-");
                    printf("%-10s ", "-");
                }
                break;
            /* 32位有符号整型参数显示处理 */
            case COT_PARAM_INT32:
                printf(" %-4d   %-24s %-10s %-6d %-8s %-10d ", paramInfo->id, paramInfo->name.pTextString,
                    "int32_t", paramInfo->length, Attr(paramInfo->attr), *paramInfo->unCurValuePtr.pInt32);

                /* 如果参数支持重置功能，显示默认值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RESET)
                    printf("%-10d ", *paramInfo->unDefValuePtr.pInt32);
                else
                    printf("%-10s ", "-");

                /* 如果参数有范围限制，显示最小值和最大值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RANGE)
                {
                    printf("%-10d ", *paramInfo->unMinValuePtr.pInt32);
                    printf("%-10d ", *paramInfo->unMaxValuePtr.pInt32);
                }
                else
                {
                    printf("%-10s ", "-");
                    printf("%-10s ", "-");
                }
                break;
            /* 64位有符号整型参数显示处理 */
            case COT_PARAM_INT64:
                printf(" %-4d   %-24s %-10s %-6d %-8s %-10lld ", paramInfo->id, paramInfo->name.pTextString,
                    "int64_t", paramInfo->length, Attr(paramInfo->attr), *paramInfo->unCurValuePtr.pInt64);

                /* 如果参数支持重置功能，显示默认值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RESET)
                    printf("%-10lld ", *paramInfo->unDefValuePtr.pInt64);
                else
                    printf("%-10s ", "-");

                /* 如果参数有范围限制，显示最小值和最大值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RANGE)
                {
                    printf("%-10lld ", *paramInfo->unMinValuePtr.pInt64);
                    printf("%-10lld ", *paramInfo->unMaxValuePtr.pInt64);
                }
                else
                {
                    printf("%-10s ", "-");
                    printf("%-10s ", "-");
                }
                break;
            /* 8位无符号整型参数显示处理 */
            case COT_PARAM_UINT8:
                printf(" %-4d   %-24s %-10s %-6d %-8s %-10u ", paramInfo->id, paramInfo->name.pTextString,
                    "uint8_t", paramInfo->length, Attr(paramInfo->attr), *paramInfo->unCurValuePtr.pUint8);

                /* 如果参数支持重置功能，显示默认值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RESET)
                    printf("%-10u ", *paramInfo->unDefValuePtr.pUint8);
                else
                    printf("%-10s ", "-");

                /* 如果参数有范围限制，显示最小值和最大值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RANGE)
                {
                    printf("%-10u ", *paramInfo->unMinValuePtr.pUint8);
                    printf("%-10u ", *paramInfo->unMaxValuePtr.pUint8);
                }
                else
                {
                    printf("%-10s ", "-");
                    printf("%-10s ", "-");
                }
                break;
            /* 16位无符号整型参数显示处理 */
            case COT_PARAM_UINT16:
                printf(" %-4d   %-24s %-10s %-6d %-8s %-10u ", paramInfo->id, paramInfo->name.pTextString,
                    "uint16_t", paramInfo->length, Attr(paramInfo->attr), *paramInfo->unCurValuePtr.pUint16);

                /* 如果参数支持重置功能，显示默认值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RESET)
                    printf("%-10u ", *paramInfo->unDefValuePtr.pUint16);
                else
                    printf("%-10s ", "-");

                /* 如果参数有范围限制，显示最小值和最大值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RANGE)
                {
                    printf("%-10u ", *paramInfo->unMinValuePtr.pUint16);
                    printf("%-10u ", *paramInfo->unMaxValuePtr.pUint16);
                }
                else
                {
                    printf("%-10s ", "-");
                    printf("%-10s ", "-");
                }
                break;
            /* 32位无符号整型参数显示处理 */
            case COT_PARAM_UINT32:
                printf(" %-4d   %-24s %-10s %-6d %-8s %-10u ", paramInfo->id, paramInfo->name.pTextString,
                    "uint32_t", paramInfo->length, Attr(paramInfo->attr), *paramInfo->unCurValuePtr.pUint32);

                /* 如果参数支持重置功能，显示默认值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RESET)
                    printf("%-10u ", *paramInfo->unDefValuePtr.pUint32);
                else
                    printf("%-10s ", "-");

                /* 如果参数有范围限制，显示最小值和最大值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RANGE)
                {
                    printf("%-10u ", *paramInfo->unMinValuePtr.pUint32);
                    printf("%-10u ", *paramInfo->unMaxValuePtr.pUint32);
                }
                else
                {
                    printf("%-10s ", "-");
                    printf("%-10s ", "-");
                }
                break;
            /* 64位无符号整型参数显示处理 */
            case COT_PARAM_UINT64:
                printf(" %-4d   %-24s %-10s %-6d %-8s %-10llu ", paramInfo->id, paramInfo->name.pTextString,
                    "uint64_t", paramInfo->length, Attr(paramInfo->attr), *paramInfo->unCurValuePtr.pUint64);

                /* 如果参数支持重置功能，显示默认值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RESET)
                    printf("%-10llu ", *paramInfo->unDefValuePtr.pUint64);
                else
                    printf("%-10s ", "-");

                /* 如果参数有范围限制，显示最小值和最大值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RANGE)
                {
                    printf("%-10llu ", *paramInfo->unMinValuePtr.pUint64);
                    printf("%-10llu ", *paramInfo->unMaxValuePtr.pUint64);
                }
                else
                {
                    printf("%-10s ", "-");
                    printf("%-10s ", "-");
                }
                break;
            /* 单精度浮点型参数显示处理 */
            case COT_PARAM_FLOAT:
                printf(" %-4d   %-24s %-10s %-6d %-8s %-10f ", paramInfo->id, paramInfo->name.pTextString,
                    "float", paramInfo->length, Attr(paramInfo->attr), *paramInfo->unCurValuePtr.pFloat);

                /* 如果参数支持重置功能，显示默认值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RESET)
                    printf("%-10f ", *paramInfo->unDefValuePtr.pFloat);
                else
                    printf("%-10s ", "-");

                /* 如果参数有范围限制，显示最小值和最大值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RANGE)
                {
                    printf("%-10f ", *paramInfo->unMinValuePtr.pFloat);
                    printf("%-10f ", *paramInfo->unMaxValuePtr.pFloat);
                }
                else
                {
                    printf("%-10s ", "-");
                    printf("%-10s ", "-");
                }
                break;
            /* 双精度浮点型参数显示处理 */
            case COT_PARAM_DOUBLE:
                printf(" %-4d   %-24s %-10s %-6d %-8s %-10f ", paramInfo->id, paramInfo->name.pTextString,
                    "double", paramInfo->length, Attr(paramInfo->attr), *paramInfo->unCurValuePtr.pDouble);

                /* 如果参数支持重置功能，显示默认值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RESET)
                    printf("%-10f ", *paramInfo->unDefValuePtr.pDouble);
                else
                    printf("%-10s ", "-");

                /* 如果参数有范围限制，显示最小值和最大值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RANGE)
                {
                    printf("%-10f ", *paramInfo->unMinValuePtr.pDouble);
                    printf("%-10f ", *paramInfo->unMaxValuePtr.pDouble);
                }
                else
                {
                    printf("%-10s ", "-");
                    printf("%-10s ", "-");
                }
                break;
    #if COT_PARAM_USE_STRING_TYPE
            /* 字符串类型参数显示处理 */
            case COT_PARAM_STRING:
                printf(" %-4d   %-24s %-10s %-6d %-8s %-10s ", paramInfo->id, paramInfo->name.pTextString,
                    "string", paramInfo->length, Attr(paramInfo->attr), paramInfo->unCurValuePtr.pString);

                /* 如果参数支持重置功能，显示默认值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RESET)
                    printf("%-10s ", paramInfo->unDefValuePtr.pString);
                else
                    printf("%-10s ", "-");

                /* 如果参数有范围限制，显示最小值和最大值 */
                if (paramInfo->attr & COT_PARAM_ATTR_RANGE)
                {
                    printf("%-10u ", *paramInfo->unMinValuePtr.pStringLength);
                    printf("%-10u ", *paramInfo->unMaxValuePtr.pStringLength);
                }
                else
                {
                    printf("%-10s ", "-");
                    printf("%-10s ", "-");
                }
                break;
    #endif
            /* 处理未知的参数类型 */
            default:
                break;
        }

        printf("\n");
    }
}
